#include <stdio.h>
#include "camdrv.h"
#include "camplus.h"

//static Uint16 s_tmpBuffer[SNAP_SHOT_WIDTH*SNAP_SHOT_HEIGHT*2];

CCamSnapshot::CCamSnapshot()
{
    m_OutFramesBuffer = NULL;
    m_ulSnapshotBufFrameLen =0;
    m_iWidth = 0;
    m_iHeight = 0;
    m_iZoom = 1;
    m_iContinuousSnaps = 1;
    m_SnapshotAppBuffer[0] = NULL;
}

void CCamSnapshot::Destroy()
{
    FreeBuffer();
    m_SnapshotAppBuffer[0] = NULL;
    m_ulSnapshotBufFrameLen =0;
    m_iWidth = 0;
    m_iHeight = 0;
}

ECode CCamSnapshot::CreateBuffer(int iWidth, int iHeight)
{
    //Create Max Buffer size once and use it always!
    m_iWidth = iWidth;
    m_iHeight = iHeight;
    m_ulSnapshotBufFrameLen = iWidth
                         * iHeight
                         * CAMERA_DATA_BYTES;

    if(NULL == m_OutFramesBuffer){
        m_OutFramesBuffer = (BYTE *)Nu_DmaBufAlloc(
            (m_ulSnapshotBufFrameLen * SNAPSHOT_FREAMS), TRUE);
        if(NULL == m_OutFramesBuffer){
            m_ulSnapshotBufFrameLen = 0;
            DRV_EXPRESSION(ERRORLEVEL,
                kprintf("m_OutFramesBuffer Nu_DmaBufAlloc failed\n"));
            return E_OUT_OF_MEMORY;
        }
        kprintf("CCamSnapshot::CreateBuffer OK, addr:0x%x.\n", m_OutFramesBuffer);
    }

    return NOERROR;

}

void CCamSnapshot::FreeBuffer()
{
    if(NULL != m_OutFramesBuffer){
        kprintf("CCamSnapshot::FreeBuffer OK. addr:0x%x\n", m_OutFramesBuffer);
        Nu_DmaBufFree((physaddr_t)m_OutFramesBuffer, (m_ulSnapshotBufFrameLen * SNAPSHOT_FREAMS));
        m_OutFramesBuffer = NULL;
    }
}

ECode CCamSnapshot::Initialize()
{
    return NOERROR;
}

void SnapshotCallBack(void *pFrameBuffer){
    g_CameraDriver.m_pSnapshot->DoSnapshot(pFrameBuffer);
}

void CCamSnapshot::DoSnapshot(void *pFrameBuffer)
{
    m_event.NotifyByIsr(SIGNALED);
//    kprintf("CCamSnapshot::DoSnapshot OK.\n");
}

ECode  CCamSnapshot::GetSnapshotFrames(int iWidth, int iHeight, Camera_Photo *pPhoto)
{
    WaitResult wr;
    EventState state;
    ECode ec;
    int i, iFrameSize;

    //Resolution changed
    if(iWidth != m_iWidth){
        FreeBuffer();
    }

    if(NULL == m_OutFramesBuffer){
        ec = CreateBuffer(iWidth, iHeight);
        if(FAILED(ec)){
            DRV_EXPRESSION(ERRORLEVEL,
                kprintf("CCamVideo Initialize CreateBuffer failed\n"));
            return ec;
        }
    }
    iFrameSize = 0;
    for(i = 0; i < SNAPSHOT_FREAMS; i++){
        m_SnapshotAppBuffer[i] = (Uint16 *)&m_OutFramesBuffer[iFrameSize];
        kprintf("CCamSnapshot mem_appBuffer[%d] 0x%x.\n",i, m_SnapshotAppBuffer[i]);
        iFrameSize += m_ulSnapshotBufFrameLen;
    }

    kprintf("GetSnapshotFrames m_OutFramesBuffer:0x%x.\n", m_OutFramesBuffer);

    if(nu_CameraStart(CAM_MODE_SNAPSHOT,
        m_SnapshotAppBuffer,
        (Uint8)SNAPSHOT_FREAMS,
        m_iWidth,
        m_iHeight,
        SnapshotCallBack)){
        DRV_EXPRESSION(ERRORLEVEL,
            kprintf("GetSnapshotFrames nu_CameraStart failed\n"));
        kprintf("CCamSnapshot::FreeBuffer OK. addr:0x%x\n", m_OutFramesBuffer);
        FreeBuffer();
        m_SnapshotAppBuffer[0] = NULL;
        return E_INVALID_OPERATION;
    }

    m_event.TryWait(10000, &wr, &state);
    if(WaitResult_OK != wr){
        kprintf("GetSnapshotFrames wait event failed\n");
        return E_TIMED_OUT;
    }
    nu_CameraStop();

    pPhoto->Number = 1;
    pPhoto->SingleBufferSize = m_ulSnapshotBufFrameLen;
    pPhoto->pBuffer = m_OutFramesBuffer;
    kprintf("GetSnapshotFrames m_OutFramesBuffer:0x%x.\n", m_OutFramesBuffer);
    kprintf("GetSnapshotFrames OK.\n");
    return NOERROR;
}

void   CCamSnapshot::ReleaseFrames()
{
    FreeBuffer();
    m_SnapshotAppBuffer[0] = NULL;

}
